package router

import (
	"container/list"
	"fmt"
	"os"
	"time"

	"gitee.com/liukexing/isrn/api/advanced"
)

import (
	ma "github.com/multiformats/go-multiaddr"
	manet "github.com/multiformats/go-multiaddr-net"
)

const ()

var (
	listenlist *list.List
)

func findListen(lsname string) (*advanced.P2PListener, error) {
	p2p := &advanced.P2pCommand{*sh}
	lslist, err := p2p.ListenerLs()
	if err != nil {
		return nil, err
	}
	for _, v := range lslist.Listeners {
		if v.Protocol == lsname {
			return &v, nil
		}
	}
	return nil, fmt.Errorf("Find listen Failed")
}

func messagePraise() {
	for {
		l := listenlist.Front()
		msgcnt := 0
		for l != nil {
			n := l.Next()
			v := l.Value.(*ConnectInfo)
			if !v.Active || time.Since(v.LastTick) > time.Minute*5 {
				closeListen(v)
				listenlist.Remove(l)
			}
			if v.Active && len(v.ReqChan) > 0 {
				data := <-v.ReqChan
				dataDecode(data, v)
				msgcnt++
			}
			l = n
		}
		if msgcnt == 0 {
			time.Sleep(time.Millisecond * 10)
		}
	}
}

func createListen(ls advanced.P2PListener) error {
	maddr, err := ma.NewMultiaddr(ls.Address)
	if err != nil {
		return err
	}

	var conn manet.Conn
	fmt.Fprintf(os.Stdout, "Start Listener \nPeerId:%s\nProtocol:%s\nAddress:%s\n", nodeid, ls.Protocol, ls.Address)
	listener, err := manet.Listen(maddr)
	if err != nil {
		fmt.Fprintf(os.Stdout, "Start Listener error:%s\n", err.Error())
		panic(err)
		return err
	}
	listenlist = list.New()
	go messagePraise()
	for {
		conn, err = listener.Accept()
		if err != nil {
			fmt.Fprintf(os.Stdout, "Listener Accept error:%s\n", err.Error())
			panic(err)
			return err
		}
		listenInfo := ConnectInfo{}
		listenInfo.Active = true
		listenInfo.Conn = conn
		listenInfo.LastTick = time.Now()
		listenInfo.ReqChan = make(chan []byte, 5)
		listenInfo.ReqStat = true
		listenInfo.ResChan = make(chan []byte, 5)
		listenInfo.ResStat = true
		listenlist.PushBack(&listenInfo)
		go receiverListen(&listenInfo)
		go sendListen(&listenInfo)
	}
}

func startListen() error {
	if ls, err := findListen("/p2p/Route"); err != nil {
		return err
	} else {
		return createListen(*ls)
	}
	return nil
}
